package com.fa4j.code.generate.service.generator.freemarker;

import com.fa4j.code.mate.model.*;
import freemarker.core.Environment;
import freemarker.ext.beans.GenericObjectModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.util.List;

@Slf4j
public class DbTypeMethod implements TemplateMethodModelEx {

    @Override
    public Object exec(List arguments) throws TemplateModelException {
        if (arguments.get(0) instanceof GenericObjectModel objectModel
                && objectModel.getWrappedObject() instanceof CodeMateField field) {
            if (field.getType() == CodeMateFieldType.STRING) {
                return field.getType().getDbType() + "(" + (field.getLength() == null ? 64 : field.getLength()) + ")";
            } else if (field.getType() == CodeMateFieldType.OBJECT) {
                CodeMateModel model = getModel(field.getModelId());
                if (model != null) {
                    if (model.getType() == CodeMateModelType.DICT) {
                        return "TINYINT UNSIGNED";
                    } else if (ObjectUtils.isEmpty(model.getTableName())) {
                        return "VARCHAR(" + (field.getLength() == null ? 512 : field.getLength()) + ")";
                    }
                }
            } else {
                return field.getType().getDbType();
            }
        }
        return null;
    }

    private CodeMateModel getModel(Integer modelId) throws TemplateModelException {
        Environment env = Environment.getCurrentEnvironment();
        TemplateModel templateModel = env.getDataModel().get("module");
        if (templateModel instanceof GenericObjectModel moduleObjectModel
                && moduleObjectModel.getWrappedObject() instanceof CodeMateModule module) {
            return module.getModelList().stream().filter(m -> m.getId().equals(modelId)).findFirst().orElse(null);

        }
        return null;
    }
}
